/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ComNo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

/**
 *
 * @author Du
 */
public class NoComCliente {

    private String servidor;      //nome do Mestre
    private int servPorta;
    private String nArq;
    private Socket conMestre;    //socket de comunicacao com o Mestre
    private InputStream in;      //stream para envia dados
    private OutputStream out;    //stream para receber dados
    private String clntlog;
    private static PrintWriter log = null;
    //Variáveis para tratar erros
    private final static int FALHA = 0;
    private final static int SUCESSO = 1;
    private final static int ARQEXISTENTE = 2;      //arquivo que está tentando ser criado já existe
    private final static int UKERRO = 3;            //erro desconhecido
    private final static int SERVERNOTFOUND = 4;

    public NoComCliente(String serv, int servPorta, String nArq) throws FileNotFoundException, UnsupportedEncodingException {
        servidor = serv;
        this.servPorta = servPorta;
        this.nArq = nArq;
        this.clntlog = "ClienteLog.txt";
        log = new PrintWriter(clntlog, "UTF-8"); //Opens log file
    }

    public int CopiarArquivo() throws IOException {

        try {
            conMestre = new Socket(servidor, servPorta);    //cria a socket para estabelecer conexão com o servidor

            System.out.println("Conectando ao mestre... enviando a mensagem");

            in = conMestre.getInputStream();          //stream para receber a resposta do servidor
            out = conMestre.getOutputStream();       //stream para enviar a mensagem ao servidor
        } catch (IOException | IllegalArgumentException | SecurityException ex) {
            System.out.println("Falha: " + ex.getMessage());
            return FALHA;
        }
        PrintStream envio = new PrintStream(out);
        long starttime = System.nanoTime();
        //envia primeiro a opcao
        envio.println("1");
        envio.flush();

        //envia o nome do arquivo
        envio.println(nArq);
        envio.flush();

        //envia o nome do host
        envio.println(InetAddress.getLocalHost().getHostName());
        envio.flush();

        //Espera para receber a resposta do mestre
        Scanner scan = new Scanner(in);
        String respostaEnd = new String();     //auxiliar só para teste
        int respostaTam = 0;                   //auxiliar só para teste
        int respostaMestre = FALHA;

        if (scan.hasNext()) {
            respostaMestre = Integer.parseInt(scan.nextLine());
        }
        if (respostaMestre == FALHA) {
            System.out.println("    Falha na copia: Arquivo inexistente");
            return respostaMestre;
        } else if (respostaMestre == UKERRO) {
            System.out.println("    Falha na copia!");
            return respostaMestre;
        } else {
            if (scan.hasNext()) {
                respostaEnd = scan.nextLine();
            }
            if (scan.hasNext()) {
                respostaTam = Integer.parseInt(scan.nextLine());
            }

            in.close();
            out.close();
            conMestre.close();
            envio.close();

            //comunica com o no que possui o arquivo
            File arq1 = new File("/opt/grupo08/" + nArq);
            FileOutputStream grava = new FileOutputStream(arq1);
            byte[] buff = new byte[respostaTam];
            Socket comunica = new Socket(respostaEnd, servPorta);
            in = comunica.getInputStream();
            out = comunica.getOutputStream();
            PrintStream envio2 = new PrintStream(out);

            //envia o código que informa que é comunicação para cópia de arquivo
            envio2.println("1");
            //envia o nome do arquivo para o nó que possui o arquivo
            envio2.println(nArq);
            envio2.flush();

            System.out.println("Nome arquivo copia: " + nArq + ".txt ......e Copiando arquivo");
            while ((in.read(buff, 0, respostaTam)) != -1) {
                grava.write(buff, 0, respostaTam);
            }
            long duration = System.nanoTime() - starttime;
            log.println(getSystemTime() + "Arquivo Copiado com sucesso: " + duration);
            System.out.println("Tempo: " + duration / 1000);
            grava.flush();
            grava.close();
            comunica.close();
            in.close();
            out.close();
            envio.close();
            return SUCESSO;
            //fim caso cliente
        }
    }

    public int ExcluirArquivo() throws IOException {
        try {
            conMestre = new Socket(servidor, servPorta);    //cria a socket para estabelecer conexão com o servidor

            System.out.println("Conectando ao mestre... enviando a mensagem");

            in = conMestre.getInputStream();          //stream para receber a resposta do servidor
            out = conMestre.getOutputStream();       //stream para enviar a mensagem ao servidor
        } catch (IOException | IllegalArgumentException | SecurityException ex) {
            System.out.println("Falha: " + ex.getMessage());
            return FALHA;
        }

        PrintStream envio = new PrintStream(out);
        long starttime = System.nanoTime();
        //envia primeiro a opcao
        envio.println("2");
        envio.flush();

        //envia o nome do arquivo
        envio.println(nArq);
        envio.flush();

        //Espera para receber a resposta do servidor
        Scanner scan = new Scanner(in);
        int respostaMestre = FALHA;       //arquivo não existe(FALHA) ou arquivo excluído(SUCESSO)

        if (scan.hasNext()) {
            respostaMestre = Integer.parseInt(scan.nextLine());
        }
        long duration = System.nanoTime() - starttime;
        log.println(getSystemTime() + "Arquivo Copiado com sucesso: " + duration);
        System.out.println("Tempo: " + duration / 1000);
        System.out.println("Status da resposta do Mestre: " + respostaMestre);
        if (respostaMestre == FALHA) {
            return respostaMestre;
        } else if (respostaMestre == SUCESSO) {
            return respostaMestre;
        } else {
            return UKERRO;
        }
    }

    public int CriaArquivo() throws IOException {        //retorno: 0(falha), 1(sucesso), 2(arquivo já existe), 3(ERRO!), 4(Servidor não encontrado)

        try {
            conMestre = new Socket(servidor, servPorta);    //cria a socket para estabelecer conexão com o servidor

            System.out.println("Conectando ao mestre... enviando a mensagem");

            in = conMestre.getInputStream();          //stream para receber a resposta do servidor
            out = conMestre.getOutputStream();       //stream para enviar a mensagem ao servidor
        } catch (UnknownHostException ex) {
            return SERVERNOTFOUND;
        }

        PrintStream envio = new PrintStream(out);
        long starttime = System.nanoTime();
        //envia primeiro a opcao
        envio.println("3");
        envio.flush();

        //envia o nome do arquivo
        envio.println(nArq);
        envio.flush();

        //Espera para receber a resposta do servidor
        Scanner scan = new Scanner(in);
        int respostaMestre = FALHA;       //arquivo já existe(ARQEXISTENTE) ou permitido para criar(SUCESSO)

        if (scan.hasNext()) {
            respostaMestre = Integer.parseInt(scan.nextLine());
        }
        long duration = System.nanoTime() - starttime;
        log.println(getSystemTime() + "Arquivo Copiado com sucesso: " + duration);
        System.out.println("Tempo: " + duration / 1000);

        if (respostaMestre == FALHA) {
            return respostaMestre;
        } else if (respostaMestre == SUCESSO) {
            try {
                File arq = new File("/opt/grupo08/" + nArq);
                arq.createNewFile();                                            //Arquivo criado
                InputStreamReader teclado = new InputStreamReader(System.in);   //ler do teclado o conteúdo q terá o arquivo
                BufferedReader br = new BufferedReader(teclado);
                FileWriter fw = new FileWriter(arq);
                BufferedWriter bw = new BufferedWriter(fw);
                bw.write(br.readLine());
                bw.flush();
                bw.close();

                //envio dos dados para serem cadastrados no BD
                //nome arquivo
                envio.println(nArq);
                //tamanho arquivo
                envio.println(String.valueOf(arq.length()));
                //nome do nó
                envio.println(InetAddress.getLocalHost().getHostName());
            } catch (IOException e) {
                return ARQEXISTENTE;
            }

            return respostaMestre;
        } else if (respostaMestre == ARQEXISTENTE) {
            return respostaMestre;
        }
        return UKERRO;
    }

    public int AtualizarArquivo() throws IOException {               //Atualiza um arquivo

        try {
            conMestre = new Socket(servidor, servPorta);    //cria a socket para estabelecer conexão com o servidor

            System.out.println("Conectando ao mestre... enviando a mensagem");

            in = conMestre.getInputStream();          //stream para receber a resposta do servidor
            out = conMestre.getOutputStream();       //stream para enviar a mensagem ao servidor
        } catch (UnknownHostException ex) {
            return SERVERNOTFOUND;
        }

        PrintStream envio = new PrintStream(out);

        //envia primeiro a opcao
        envio.println("4");
        envio.flush();

        //envia o nome do arquivo
        envio.println(nArq);
        envio.flush();

        //Espera para receber a resposta do servidor
        Scanner scan = new Scanner(in);
        int respostaMestre = FALHA;       //arquivo já existe(ARQEXISTENTE) ou permitido para criar(SUCESSO)

        if (scan.hasNext()) {
            respostaMestre = Integer.parseInt(scan.nextLine());
        }
        if (respostaMestre == SUCESSO) {
            try {
                File arq = new File("/opt/grupo08/" + nArq);
                System.out.println("    Digite o texto:");
                arq.createNewFile();                                            //Arquivo criado
                InputStreamReader teclado = new InputStreamReader(System.in);   //ler do teclado o conteúdo q terá o arquivo
                BufferedReader br = new BufferedReader(teclado);
                FileWriter fw = new FileWriter(arq);
                BufferedWriter bw = new BufferedWriter(fw);
                bw.write(br.readLine());
                bw.flush();
                bw.close();

                //envio dos dados para serem cadastrados no BD
                //nome arquivo
                envio.println(nArq);
                //tamanho arquivo
                envio.println(arq.length());
                //nome do nó
                envio.println(InetAddress.getLocalHost().getHostName());
            } catch (IOException e) {
                return ARQEXISTENTE;
            }

            return respostaMestre;
        } else {
            return FALHA;
        }
    }

    public static String getSystemTime() {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss ");
        Date date = new Date();
        return dateFormat.format(date);
    }
}
